﻿#region Imports
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Reflection;
using DataAnnotationsContrib.Commerce;
using DataAnnotationsContrib.Interfaces;
using DataAnnotationsContrib.Tests.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endregion

namespace DataAnnotationsContrib.Tests.Commerce
{
    /// <summary>
    /// </summary>
    [TestClass]
    public class UpuPostalCodeAlgorithmTest : ValidationAlgorithmTest<UpuPostalCodeAlgorithm>
    {
        #region Data
        private static readonly List<string> __validValues = new List<string>();
        private static readonly List<string> __inValidValues = new List<string>();
        private static readonly List<string> __countryCodes = new List<string>();
        private static readonly List<string> __inValidCountryCodes = new List<string>();
        #endregion

        static UpuPostalCodeAlgorithmTest()
        {
            var thisAssembly = typeof(UpuPostalCodeAlgorithmTest).Assembly;

            var stream = thisAssembly.GetManifestResourceStream("DataAnnotationsContrib.Tests.Resources.UpuPostalCodeAlgorithmValidTestData.csv");
            using (var reader = new StreamReader(stream))
            {
                bool firstLine = true;
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    if (!firstLine && !line.StartsWith("--"))
                    {
                        string[] parts = line.Split(';');
                        __validValues.Add(parts[1]);
                        __countryCodes.Add(parts[0]);
                    }
                    firstLine = false;
                }
            }


            stream = thisAssembly.GetManifestResourceStream("DataAnnotationsContrib.Tests.Resources.UpuPostalCodeAlgorithmInvalidTestData.csv");
            using (var reader = new StreamReader(stream))
            {
                bool firstLine = true;
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    if (!firstLine && !line.StartsWith("--"))
                    {
                        string[] parts = line.Split(';');
                        __inValidValues.Add(parts[1]);
                        __inValidCountryCodes.Add(parts[0]);
                    }
                    firstLine = false;
                }
            }
        }

        public UpuPostalCodeAlgorithmTest()
            : base(__validValues, __inValidValues)
        { }

        private UpuPostalCodeAlgorithm CreateAlgorithm(string countryCode)
        {
            return new UpuPostalCodeAlgorithm(countryCode);
        }

        #region Tests
        [TestMethod]
        public void AllValidValuesShouldValidateTrue_ForAlgorithmAcceptingAllCountries()
        {
            TestAllValidValuesShouldValidateTrue();
        }
        [TestMethod]
        public void AllValidValuesShouldValidateTrue_ForAlgorithmLimitedToSpecificCountry()
        {
            TestHelper.Trace(this.TestContext, __validValues);

            for (int i = 0; i < __validValues.Count; i++)
            {
                string country = __countryCodes[i];
                string value = __validValues[i];

                var algorithm = CreateAlgorithm(country);
                Assert.IsTrue(algorithm.Validate(value), String.Format("Value '{0}' unexpectedly failed validation for country '{1}'.", value, country));
            }
        }
        [TestMethod]
        public void AllInvalidValuesShouldValidateFalse_ForAlgorithmLimitedToSpecificCountry()
        {
            TestHelper.Trace(this.TestContext, __inValidValues);

            for (int i = 0; i < __inValidValues.Count; i++)
            {
                string country = __inValidCountryCodes[i];
                string value = __inValidValues[i];

                var algorithm = CreateAlgorithm(country);
                Assert.IsFalse(algorithm.Validate(value), String.Format("Value '{0}' unexpectedly passed validation for country '{1}'.", value, country));
            }
        }

        [TestMethod]
        public void ShouldInferCountryCode()
        {
            for (int i = 0; i < __validValues.Count; i++)
            {
                string country = __countryCodes[i];
                string value = __validValues[i];

                string[] matchingCountries = UpuPostalCodeAlgorithm.InferCountryCode(value);
                TestHelper.Trace(this.TestContext, country + ":" + value);
                TestHelper.Trace(this.TestContext, matchingCountries);
                Assert.IsTrue(Array.Exists(matchingCountries, s => s == country), String.Format("Value '{0}' was not correctly inferred as being valid for country '{1}'.", value, country));
            }
        }

        [TestMethod]
        public void LogFormat()
        {
            LogAllFormatStructureInfo(UpuPostalCodeAlgorithm.Formats, f=>String.Format("{0} ({1})", f.CountryCode, f.CountryName));
        }
        #endregion
    }
}
